/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "Tracer.h"
#include "ArgUtil.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

using namespace std;

namespace libemb{
ArgOption::ArgOption()
{
	memset((void*)m_longOptionsPattern,0,sizeof(struct option)*$LONG_OPT_MAX);
}

ArgOption::~ArgOption()
{
}

bool ArgOption::addOption(std::string option,int args)
{
	if (option.size()==1)
	{
		m_shortOptions.append(option);
		m_shortOptionPattern.append(option);
		switch(args){
		case 0:
			break;
		case 1:
			m_shortOptionPattern.append(":");
			break;
		default:
			m_shortOptionPattern.append("::");
			break;
		}
	}
	else if(option.size()>1)
	{
		int index = m_longOptions.size();
		if (index>$LONG_OPT_MAX)
		{
			TRACE_ERR_CLASS("long option args out of range: %d\n",$LONG_OPT_MAX);
			return false;
		}
		m_longOptions.emplace_back(option);
		struct option* opt = &(m_longOptionsPattern[index]);
		opt->name = CSTR(m_longOptions.back());
		switch(args){
		case 0:
			opt->has_arg = no_argument;
			break;
		case 1:
			opt->has_arg = required_argument;
			break;
		default:
			TRACE_ERR_CLASS("long option args cannot be: %d\n",args);
			return false;
		}
		opt->flag = NULL;
		opt->val = index;/* 返回长参数索引值 */
	}
	return true;
}

void ArgOption::parseArgs(int argc, char* argv[])
{
	int rc ;
	while(1)
	{
		rc = getopt_long(argc,argv,CSTR(m_shortOptionPattern),m_longOptionsPattern,0);
		if (rc<0)
		{
			break;
		}
		else if(rc<$LONG_OPT_MAX)
		{
			int index = rc;
			std::string value="";
			std::string option = m_longOptions[index];
			if (optarg!=NULL)
			{
				value = std::string(optarg);
			}
			m_optionMap.emplace(std::make_pair(option,value));
		}
		else
		{
			for(auto i=0; i<m_shortOptions.size(); i++)
			{
				char ch = (char)rc;
				if (m_shortOptions[i]==ch)
				{
					std::string value="";
					std::string option(1,ch);
					if (optarg!=NULL)
					{
						value = std::string(optarg);
					}
					m_optionMap.emplace(std::make_pair(option,value));
				}
			}
		}
	}
}

bool ArgOption::getValue(std::string option, std::string& value)
{
	if(option.empty())
	{
		return false;
	}
	auto iter = m_optionMap.find(option);
	if(iter!=m_optionMap.end())
	{
		value = iter->second;
		return true;
	}
    else
    {
        return false;
    }
}

InputGet::InputGet()
{

}

InputGet::~InputGet()
{

}

void InputGet::waitInput()
{
	 std::cin >> m_inputStr;
}

bool InputGet::match(std::string item)
{
	if (m_inputStr==item)
	{
		return true;
	}
	return false;
}
int InputGet::size()
{
	return m_inputStr.size();
}

int InputGet::toInt()
{
	if (m_inputStr.empty())
	{
		return 0;
	}
	return atoi(CSTR(m_inputStr));
}

float InputGet::toFloat()
{
	if (m_inputStr.empty())
	{
		return 0.0;
	}
	return atof(CSTR(m_inputStr));
}

std::string InputGet::toString()
{
	return m_inputStr;
}

const char* InputGet::toCString()
{
	return CSTR(m_inputStr);
}

}
